<?php
/**
 * csrf token检查
 * @author yupoxiong<i@yupoxiong.com>
 */

declare (strict_types=1);

namespace app\admin\middleware;

use Webman\Http\Request;
use Webman\Http\Response;
use Webman\MiddlewareInterface;

class CsrfTokenCheck implements MiddlewareInterface
{
    public const TOKEN_FIELD = '__token__';

    public function process(Request $request, callable $handler): Response
    {
        $is_check = (bool)setting('admin.safe.check_token');
        // 未开启或者get，head，option请求不验证
        if (!$is_check || in_array((request())->method(), ['GET', 'HEAD', 'OPTIONS'], false)) {
            return $handler($request);
        }

        // 排除获取token的url
        $request_url = get_request_url();
        if(strtolower($request_url)==='admin/auth/token'){
            return $handler($request);
        }

        $session = $request->session();
        $token   = self::TOKEN_FIELD;
        if (!$session->has($token)) {
            return admin_error('非法请求，请刷新页面后重试');
        }
        // header验证
        if ($request->header('X-CSRF-TOKEN') && $session->get($token) === $request->header('X-CSRF-TOKEN')) {

            $session->delete($token);
            return $handler($request);
        }

        $data = $request->all();
        // body验证
        if (isset($data[$token]) && $session->get($token) === $data[$token]) {

            $session->delete($token);
            return $handler($request);
        }

        $session->delete($token);

        return admin_error('非法请求，请刷新页面后重试');
    }
}
